/*
遍历磁盘，并列举所有卷加载点
利用命令行参数d:\test\ D:\，实现将指定的卷挂载到指定挂载点
最后再删除挂载点
需用管理员权限打开

GetLogicalDrives函数获取所有磁盘驱动器的位掩码
GetVolumeNameForVolumeMountPoint函数依据磁盘根路径获取卷GUID路径
GetVolumeInformation函数获取dwFileSystemFlags属性，判断是否NTFS
FindFirstVolumeMountPoint、FindNextVolumeMountPoint函数获取卷加载点
FindVolumeMountPointClose函数
SetVolumeMountPoint、DeleteVolumeMountPoint函数
_tprintf、sprintf_s函数
*/
#include <windows.h>
#include <stdio.h>
#include <TCHAR.H>

#define VOLROOTPATHLEN 4

void EnumMountPoint(void);
int ChkVolNtfs(PTSTR VolRootPath);
int GetVolGUID(PCTSTR VolRootPath, PTSTR VolGUID);
void GetVolMountPoint(PTSTR VolGUID);
void SetVolMount(PCTSTR VolPath, PCTSTR VolMountPoint, PTSTR VolGUID);
void DelVolMount(PCTSTR VolMountPoint);

int _tmain(int argc, PCTSTR argv[])
{
    TCHAR VolGUID[MAX_PATH];

    if (argc!=3) {
        // 列举所有驱动器的卷加载点
        EnumMountPoint();
        _tprintf(TEXT("\n\n用法： %s <挂载点> <挂载卷>\n"), *argv);
        _tprintf(TEXT("例如, \"%s c:\\mnt\\fdrive\\ f:\\\"\n"), *argv);
        return -1;
    }

    // 依据程序的第2个形参，获取卷GUID路径
    if (GetVolGUID(*(argv+2), VolGUID)!=TRUE) {
        return -2;
    }

    // 将指定的卷挂载到指定挂载点
    SetVolMount(*(argv+2), *(argv+1), VolGUID);

    // 删除挂载点
    DelVolMount(*(argv+1));
    
    return 0;
}

/* 列举所有驱动器的卷加载点 */
void EnumMountPoint(void)
{
    // 存储驱动器根路径的字符数组
    TCHAR VolRootPath[VOLROOTPATHLEN];
    // 存储卷GUID路径的字符数组
    TCHAR VolGUID[MAX_PATH];
    int iCnt=0;
    // 获取所有磁盘驱动器的位掩码
    DWORD dwVolRootPathBin = GetLogicalDrives();

    for (;dwVolRootPathBin; dwVolRootPathBin>>=1, iCnt++) {
        if ((dwVolRootPathBin&1)==1) {
            // 通过格式化字符串，获取驱动器根路径的字符串
            sprintf_s(VolRootPath, VOLROOTPATHLEN, "%c:\\", 'A'+iCnt);
            // 获取卷GUID路径
            if (GetVolGUID(VolRootPath, VolGUID)==0) {
                continue;
            }
            // 判断是否NTFS磁盘
            if (ChkVolNtfs(VolRootPath)==0) {
                continue;
            }
            // 获取卷挂载点
            GetVolMountPoint(VolGUID);
        }
    }
}

/* 判断是否NTFS磁盘 */
int ChkVolNtfs(PTSTR VolRootPath)
{
    DWORD dwFileSystemFlags;
    TCHAR FileSystemNameBuffer[MAX_PATH];

    GetVolumeInformation(VolRootPath, NULL, 0, NULL, NULL, &dwFileSystemFlags, FileSystemNameBuffer, MAX_PATH);

    if (!(dwFileSystemFlags&FILE_SUPPORTS_REPARSE_POINTS)) {
        printf("\t该文件系统不支持卷挂载点.\n");
        return 0;
    }

    return 1;
}

/* 获取卷GUID路径 */
int GetVolGUID(PCTSTR VolRootPath, PTSTR VolGUID)
{
    BOOL bFlag;

    bFlag = GetVolumeNameForVolumeMountPoint(VolRootPath, VolGUID, MAX_PATH);

    if (bFlag==TRUE) {
        printf("%s 的卷GUID路径是： %s\n", VolRootPath, VolGUID);
    } else {
        printf("无法找到 %s 的卷GUID路径\n", VolRootPath);
        return 0;
    }

    return 1;
}

/* 获取卷挂载点 */
void GetVolMountPoint(PTSTR VolGUID)
{
    HANDLE hVol;
    TCHAR VolMountPoint[MAX_PATH];
    int iVolMountPointNum = 0;
    BOOL bFlag;

    hVol = FindFirstVolumeMountPoint(VolGUID, VolMountPoint, MAX_PATH);

    if (hVol!=INVALID_HANDLE_VALUE) {
        do {
            printf("\t第%d个挂载点是 %s \n", ++iVolMountPointNum, VolMountPoint);
        } while ((bFlag = FindNextVolumeMountPoint(hVol, VolMountPoint, MAX_PATH)));

        FindVolumeMountPointClose(hVol);
    } else {
        printf("\t没有找到卷的挂载点!\n");
    }
    printf("\n\n");
}

/* 将指定的卷挂载到指定挂载点 */
void SetVolMount(PCTSTR VolPath, PCTSTR VolMountPoint, PTSTR VolGUID)
{
    BOOL bFlag;

    bFlag = SetVolumeMountPoint(VolMountPoint, VolGUID);

    if (!bFlag) {
        _tprintf(TEXT("无法把卷 %s 加载到 %s 。\n"), VolPath, VolMountPoint);
    } else {
        _tprintf(TEXT("成功把卷 %s 加载到 %s 。\n"), VolPath, VolMountPoint);
    }
}

/* 删除挂载点 */
void DelVolMount(PCTSTR VolMountPoint)
{
    BOOL bFlag;

    bFlag = DeleteVolumeMountPoint(VolMountPoint);

    if (!bFlag) {
        _tprintf(TEXT("无法删除加载点 %s 。\n"), VolMountPoint);
    } else {
        _tprintf(TEXT("成功删除加载点 %s 。\n"), VolMountPoint);
    }
}